package com.weixing.mall.provider.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.weixing.mall.base.enums.SnCodeEnum;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.base.enums.WhetherEnum;
import com.weixing.mall.provider.api.model.vo.ActivityProductVo;
import com.weixing.mall.provider.api.model.vo.ItemVo;
import com.weixing.mall.provider.api.model.vo.ProductStockVo;
import com.weixing.mall.provider.api.service.GoodsTransBillServiceRpc;
import com.weixing.mall.provider.api.service.ItemFeign;
import com.weixing.mall.provider.mapper.ProductStockMapper;
import com.weixing.mall.provider.mapper.StockCheckMapper;
import com.weixing.mall.provider.mapper.StockCheckProductMapper;
import com.weixing.mall.provider.mapper.StockCheckProductPersonMapper;
import com.weixing.mall.provider.model.domain.StockCheck;
import com.weixing.mall.provider.model.domain.StockCheckProduct;
import com.weixing.mall.provider.model.domain.StockCheckProductPerson;
import com.weixing.mall.provider.model.dto.*;
import com.weixing.mall.provider.model.enums.DepotTypeEunm;
import com.weixing.mall.provider.model.query.StockCheckDetailsQuery;
import com.weixing.mall.provider.model.query.StockCheckQuery;
import com.weixing.mall.provider.model.vo.*;
import com.weixing.mall.provider.service.IInDepotBillService;
import com.weixing.mall.provider.service.IOutDepotBillService;
import com.weixing.mall.provider.service.IStockCheckProductService;
import com.weixing.mall.provider.service.IStockCheckService;
import com.weixing.mall.provider.util.DepotUtil;
import com.weixing.mall.util.ListUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 仓库模块-盘点单 服务实现类
 * </p>
 *
 * @author Small
 * @since 2019-11-15
 */
@Service
public class StockCheckServiceImpl extends ServiceImpl<StockCheckMapper, StockCheck> implements IStockCheckService {

    @Autowired
    private StockCheckProductMapper stockCheckProductMapper;
    @Autowired
    private StockCheckProductPersonMapper stockCheckProductPersonMapper;
    @Autowired
    private ProductStockMapper productStockMapper;

    @Autowired
    private ItemFeign itemFeign;
    @Autowired
    private IStockCheckProductService stockCheckProductService;
    @Autowired
    private GoodsTransBillServiceRpc goodsTransBillServiceRpc;
    @Autowired
    private IOutDepotBillService outDepotBillService;
    @Autowired
    private IInDepotBillService inDepotBillService;

    @Override
    public IPage<StockCheckVo> selectList(Page page, StockCheckQuery stockCheckQuery) {
        return baseMapper.selectOfPage(page, stockCheckQuery);
    }

    @Override
    @Transactional
    public void save(StockCheckDto stockCheckDto, Long uid) {
        StockCheck stockCheck = new StockCheck();
        BeanUtils.copyProperties(stockCheckDto, stockCheck);
        if (stockCheckDto.getId() == null) {
            stockCheck.setCreatedBy(uid);
            stockCheck.setCreatedTime(new Date());
            stockCheck.setIsFinish(WhetherEnum.NO.getValue());
            stockCheck.setIsPublish(WhetherEnum.NO.getValue());
            save(stockCheck);
            /*盘点仓库数据初始化操作*/
            try {
                //initStockProduct(stockCheckDto.getDepot(), stockCheck.getId());
                stockCheckProductService.insertStockCheckProductByDepotId(stockCheckDto.getDepot(), stockCheck.getId(), uid);
            } catch (RuntimeException e) {
                e.getMessage();
            }
            //添加盘点单号
            StockCheck s = new StockCheck();
            String checkSn = DepotUtil.genCheckSn(stockCheck.getId());
            s.setId(stockCheck.getId());
            s.setCheckSn(checkSn);
            updateById(s);
        } else {
            updateById(stockCheck);
        }
    }

    private void initStockProduct(Long depot, Long stockCheckId) {
        List<ProductStockVo> list = productStockMapper.getAllByDepotId(depot);
        List<Long> courseIds = list.stream().map(ProductStockVo::getProductId).collect(Collectors.toList());
        long[] productIds = new long[courseIds.size()];
        for (int i = 0; i < courseIds.size(); i++) {
            productIds[i] = courseIds.get(i);
        }
        List<ActivityProductVo> productVos = itemFeign.findActProductVoByIds(productIds).getData();
        for (ProductStockVo vo : list) {
            int flag = 0;//减少循环
            StockCheckProduct entity = new StockCheckProduct();
            entity.setAccountQuantity(vo.getStock());
            entity.setCheckId(stockCheckId);
            if (flag == 0) {
                for (ActivityProductVo productVo : productVos) {
                    if (vo.getProductId().equals(productVo.getId())) {
                        entity.setProductName(productVo.getGoodsName());
                        entity.setCost(new BigDecimal(productVo.getMarketPrice()));
                        entity.setProductId(productVo.getId());
                        flag = 1;
                    }
                }
            }
            stockCheckProductMapper.insert(entity);
        }
    }

    @Override
    public IPage<StockCheckSpecificDetailsVo> selectSpecificDetails(Page page, Long checkId, Long stockPerson) {
        return baseMapper.selectSpecificDetails(page, checkId, stockPerson);
    }

    @Override
    public Map<String, Object> selectSpecificDetailsReturnMap(Page page, Long checkId, Long stockPerson) {
        Map<String, Object> map = new HashMap<>();
        IPage<StockCheckSpecificDetailsVo> pageList = baseMapper.selectSpecificDetails(page, checkId, stockPerson);
        int typeTotal = 0;
        int quantityTotal = 0;
      /*  if (pageList.getRecords() != null && pageList.getRecords().size() > 0) {
            for (StockCheckSpecificDetailsVo scsdv : pageList.getRecords()) {
                if (scsdv.getQuantity() != null) {
                    quantityTotal += scsdv.getQuantity();
                }
            }
            typeTotal = pageList.getRecords().size();
        }*/
        typeTotal = pageList.getRecords().size();
        map.put("typeTotal", typeTotal);
        map.put("quantityTotal", typeTotal);
        map.put("pageList", pageList);
        return map;
    }

    @Override
    public IPage<StockCheckDetailsVo> selectDetails(Page page, StockCheckDetailsQuery stockCheckDetailsQuery) {
        return baseMapper.selectDetails(page, stockCheckDetailsQuery);
    }

    @Override
    public void updateSpecificDetails(StockCheckNumDto stockCheckNumDto) {

        //关联盘点人表id
        Long productPersonId = stockCheckNumDto.getCheckProductPersonId();
        //盘点单关联商品表id
        Long checkProduct = stockCheckNumDto.getCheckProduct();
        StockCheckProductPerson stockCheckProductPerson = stockCheckProductPersonMapper.selectById(productPersonId);
        //修改前后数量差
        int quantityDiff = stockCheckNumDto.getQuantity() - stockCheckProductPerson.getQuantity();
        //修改关联盘点人表
        stockCheckProductPersonMapper.updateSpecificDetails(productPersonId, stockCheckNumDto.getQuantity());

        StockCheckProduct stockCheckProduct = stockCheckProductMapper.selectById(checkProduct);
        //修改后盘点关联表里面的盘点数量
        int CheckQuantity = stockCheckProduct.getCheckQuantity() + quantityDiff;
        //盈亏数
        int losses = stockCheckProduct.getLosses() + quantityDiff;
        //修改盘点关联商品表
        stockCheckProductMapper.updateSpecificDetails(checkProduct, CheckQuantity, losses);
    }

    /**
     * 二期库存每条记录都修改为1，不存在更新库存数值的说法了
     * @param stockCheckNumDto
     */
    @Override
    public void delSpecificDetails(StockCheckNumDto stockCheckNumDto) {

        //关联盘点人表id
        Long productPersonId = stockCheckNumDto.getCheckProductPersonId();
        //盘点单关联商品表id
        Long checkProduct = stockCheckNumDto.getCheckProduct();
        //删除
        stockCheckProductPersonMapper.deleteById(productPersonId);

       /* StockCheckProduct stockCheckProduct = stockCheckProductMapper.selectById(checkProduct);
        //修改后盘点关联表里面的盘点数量
        int CheckQuantity = stockCheckProduct.getCheckQuantity() - stockCheckNumDto.getQuantity();
        //盈亏数减去删除的数量
        int losses = stockCheckProduct.getLosses() - stockCheckNumDto.getQuantity();
        //修改盘点关联商品表
        stockCheckProductMapper.updateSpecificDetails(checkProduct, CheckQuantity, losses);*/
    }

    /*结束完成盘点*/
    @Override
    public void finish(Long stockCheckDtoId, Long uid) {
        StockCheck stockCheck = getById(stockCheckDtoId);
        Long depotId = null;
        if (ObjectUtil.isNotEmpty(stockCheck)) {
            depotId = stockCheck.getDepot();
        }
        /*查询所有人的盘点单信息，按照活动进行*/
        List<StockCheckProductVo> list = stockCheckProductPersonMapper.sumByCheckId(stockCheckDtoId);
        List<StockCheckProduct> voList = stockCheckProductMapper.selectProduct(stockCheckDtoId);
        List<OutDepotBillProductDto> outDepotBillDtoList = Lists.newArrayList();
        List<InDepotBillProductDto> inDepotBillDtoList = Lists.newArrayList();
        for (StockCheckProductVo stockCheckVo : list) {
            StockCheckProduct stockCheckProduct = new StockCheckProduct();
            for (StockCheckProduct productStockVo : voList) {
                if (stockCheckVo.getProductId().equals(productStockVo.getProductId())) {
                    stockCheckProduct.setCheckQuantity(stockCheckVo.getSum());
                    stockCheckProduct.setLosses(stockCheckVo.getSum() - productStockVo.getAccountQuantity());
                    stockCheckProduct.setUnit(stockCheckVo.getUnit());
                    stockCheckProduct.setId(productStockVo.getId());
                    stockCheckProductMapper.updateById(stockCheckProduct);
                    Result<ItemVo> itemVoResult = itemFeign.findById(productStockVo.getProductId());
                    ItemVo itemVo = itemVoResult.isSuccess() ? itemVoResult.getData() : null;
                    //出入库封装
                    if (stockCheckProduct.getLosses() > 0 && ObjectUtil.isNotEmpty(itemVo)) {//入库
                        InDepotBillProductDto idbpd = new InDepotBillProductDto();
                        //idbpd.setInDepotId(depotId);//入库单id"
                        idbpd.setProductSn(itemVo.getProductSn());//货品编号
                        idbpd.setGoodsSn(itemVo.getGoodsSn());//货号
                        idbpd.setStyleNo(itemVo.getStyleNo());//款号
                        idbpd.setProductId(itemVo.getProductId());//商品id
                        idbpd.setGoodsId(itemVo.getGoodsId());//商品货号
                        idbpd.setGoodsName(itemVo.getProductName());//名称 ----------------goodsName和productName 已被统一
                        idbpd.setQuantity(stockCheckProduct.getLosses());//数量
                        idbpd.setSpec(itemVo.getProductSkuDesp());//规格
                        idbpd.setStatus(0);//状态  无作用
                        inDepotBillDtoList.add(idbpd);
                    } else if (stockCheckProduct.getLosses() < 0 && ObjectUtil.isNotEmpty(itemVo)) {//出库
                        OutDepotBillProductDto odbpd = new OutDepotBillProductDto();
                        //odbpd.setOutDepotId(depotId);//入库单id
                        odbpd.setProductSn(itemVo.getProductSn());//货号编号
                        odbpd.setGoodsSn(itemVo.getGoodsSn());//货号
                        odbpd.setStyleNo(itemVo.getStyleNo());//款号
                        odbpd.setProductId(itemVo.getProductId());//商品id
                        odbpd.setGoodsId(itemVo.getGoodsId());//商品货号
                        odbpd.setGoodsName(itemVo.getProductName());//名称 ----------------goodsName和productName 已被统一
                        odbpd.setQuantity(stockCheckProduct.getLosses());//数量
                        odbpd.setSpec(itemVo.getProductSkuDesp());//规格
                        odbpd.setStatus(0);//状态  无作用
                        outDepotBillDtoList.add(odbpd);
                    }
                }
            }
        }
        /*盘点结束*/
        if (ObjectUtil.isNotEmpty(stockCheck)) {
            stockCheck.setIsFinish(WhetherEnum.YES.getValue());
            updateById(stockCheck);
        }
        //盘点结束调用生成出入库单
        if (outDepotBillDtoList.size() > 0) {//生成出库单

            OutDepotBillDto outDepotBillDto = new OutDepotBillDto();
            outDepotBillDto.setOutputDepot(depotId);
            outDepotBillDto.setBillSn(outDepotBillService.getOutBillSn(SnCodeEnum.OUTBILLSN.getValue()));
            outDepotBillDto.setOutDepotType(DepotTypeEunm.TYPE_7);
            outDepotBillDto.setIsFinish(WhetherEnum.YES);
            outDepotBillDto.setProducts(outDepotBillDtoList);
            outDepotBillService.save(outDepotBillDto, uid);
        }
        if (inDepotBillDtoList.size() > 0) {//生成入库单
            /* InDepotBillVo bill = inDepotBillService.findMaxId();*/
            InDepotBillDto inDepotBillDto = new InDepotBillDto();
            inDepotBillDto.setInputDepot(depotId);
            inDepotBillDto.setBillSn(inDepotBillService.getInBillSn(SnCodeEnum.INBILLSN.getValue()));
            inDepotBillDto.setInDepotType(DepotTypeEunm.TYPE_7);
            inDepotBillDto.setIsFinish(WhetherEnum.YES);
            inDepotBillDto.setProducts(inDepotBillDtoList);
            inDepotBillService.save(inDepotBillDto, uid);
        }
    }

    @Override
    public void mergeStockCheck(Long stockCheckDtoId, Long uid) {
        /*查询所有人的盘点单信息，按照活动进行*/
        List<StockCheckProductVo> list = stockCheckProductPersonMapper.sumByCheckId(stockCheckDtoId);
        List<StockCheckProduct> voList = stockCheckProductMapper.selectProduct(stockCheckDtoId);
        //批量集合
        List<StockCheckProduct> scpList = Lists.newArrayList();
        //过滤标记
        Map<Long, Object> map = new HashMap();
        for (StockCheckProductVo stockCheckVo : list) {
            StockCheckProduct stockCheckProduct = new StockCheckProduct();
            for (StockCheckProduct productStockVo : voList) {
                if (stockCheckVo.getProductId().equals(productStockVo.getProductId())) {
                    stockCheckProduct.setCheckQuantity(stockCheckVo.getSum());
                    stockCheckProduct.setLosses(stockCheckVo.getSum() - productStockVo.getAccountQuantity());
                    stockCheckProduct.setUnit(stockCheckVo.getUnit());
                    stockCheckProduct.setId(productStockVo.getId());
                    map.put(productStockVo.getId(), productStockVo.getId());
                    scpList.add(stockCheckProduct);
                }
            }
        }
        voList.forEach(scp -> {
            if (map.get(scp.getId()) == null) {
                StockCheckProduct stockCheckProduct = new StockCheckProduct();
                stockCheckProduct.setLosses(scp.getCheckQuantity() - scp.getAccountQuantity());
                stockCheckProduct.setId(scp.getId());
                scpList.add(stockCheckProduct);
            }
        });
        if (scpList != null && scpList.size() > 0) {
            stockCheckProductService.updateBatchById(scpList,ListUtil.SIZE);
        }
    }

    @Override
    public void finishDepot(Long stockCheckDtoId, Long uid) {
        StockCheck stockCheck = getById(stockCheckDtoId);
        Long depotId = null;
        if (ObjectUtil.isNotEmpty(stockCheck)) {
            depotId = stockCheck.getDepot();
        }
        List<StockCheckProduct> voList = stockCheckProductMapper.selectProduct(stockCheckDtoId);
        List<OutDepotBillProductDto> outDepotBillDtoList = Lists.newArrayList();
        List<InDepotBillProductDto> inDepotBillDtoList = Lists.newArrayList();
        for (StockCheckProduct scp : voList) {
            Result<ItemVo> itemVoResult = itemFeign.findById(scp.getProductId());
            ItemVo itemVo = itemVoResult.isSuccess() ? itemVoResult.getData() : null;
            //出入库封装
            if (scp.getLosses() > 0 && ObjectUtil.isNotEmpty(itemVo)) {//入库
                InDepotBillProductDto idbpd = new InDepotBillProductDto();
                //idbpd.setInDepotId(depotId);//入库单id"
                idbpd.setProductSn(itemVo.getProductSn());//货品编号
                idbpd.setGoodsSn(itemVo.getGoodsSn());//货号
                idbpd.setStyleNo(itemVo.getStyleNo());//款号
                idbpd.setProductId(itemVo.getProductId());//商品id
                idbpd.setGoodsId(itemVo.getGoodsId());//商品货号
                idbpd.setGoodsName(itemVo.getProductName());//名称 ----------------goodsName和productName 已被统一
                idbpd.setQuantity(scp.getLosses());//数量
                idbpd.setSpec(itemVo.getProductSkuDesp());//规格
                idbpd.setStatus(0);//状态  无作用
                inDepotBillDtoList.add(idbpd);
            } else if (scp.getLosses() < 0 && ObjectUtil.isNotEmpty(itemVo)) {//出库
                OutDepotBillProductDto odbpd = new OutDepotBillProductDto();
                //odbpd.setOutDepotId(depotId);//入库单id
                odbpd.setProductSn(itemVo.getProductSn());//货号编号
                odbpd.setGoodsSn(itemVo.getGoodsSn());//货号
                odbpd.setStyleNo(itemVo.getStyleNo());//款号
                odbpd.setProductId(itemVo.getProductId());//商品id
                odbpd.setGoodsId(itemVo.getGoodsId());//商品货号
                odbpd.setGoodsName(itemVo.getProductName());//名称 ----------------goodsName和productName 已被统一
                odbpd.setQuantity(scp.getLosses());//数量
                odbpd.setSpec(itemVo.getProductSkuDesp());//规格
                odbpd.setStatus(0);//状态  无作用
                outDepotBillDtoList.add(odbpd);
            }
        }

        /*盘点结束*/
        if (ObjectUtil.isNotEmpty(stockCheck)) {
            stockCheck.setIsFinish(WhetherEnum.YES.getValue());
            updateById(stockCheck);
        }

        //盘点结束调用生成出入库单
        if (outDepotBillDtoList.size() > 0) {//生成出库单
            OutDepotBillDto outDepotBillDto = new OutDepotBillDto();
            outDepotBillDto.setOutputDepot(depotId);
            outDepotBillDto.setBillSn(outDepotBillService.getOutBillSn(SnCodeEnum.OUTBILLSN.getValue()));
            outDepotBillDto.setOutDepotType(DepotTypeEunm.TYPE_7);
            outDepotBillDto.setIsFinish(WhetherEnum.YES);
            outDepotBillDto.setProducts(outDepotBillDtoList);
            outDepotBillService.save(outDepotBillDto, uid);
        }
        if (inDepotBillDtoList.size() > 0) {//生成入库单
            InDepotBillDto inDepotBillDto = new InDepotBillDto();
            inDepotBillDto.setInputDepot(depotId);
            inDepotBillDto.setBillSn(inDepotBillService.getInBillSn(SnCodeEnum.INBILLSN.getValue()));
            inDepotBillDto.setInDepotType(DepotTypeEunm.TYPE_7);
            inDepotBillDto.setIsFinish(WhetherEnum.YES);
            inDepotBillDto.setProducts(inDepotBillDtoList);
            inDepotBillService.save(inDepotBillDto, uid);
        }
    }

    /**
     * 盘点单详情
     * @param checkId
     * @param uid
     * @return
     */
    @Override
    public Map<String, Object> specificDetailTotal(Long checkId, Long uid) {
        Map<String, Object> result = new HashMap<String, Object>();
        Integer total = stockCheckProductPersonMapper.selectCount(new QueryWrapper<StockCheckProductPerson>().eq("check_id", checkId).eq("stock_person", uid));
        Integer styletotal = stockCheckProductPersonMapper.selectCount(new QueryWrapper<StockCheckProductPerson>().groupBy("style_no").eq("check_id", checkId).eq("stock_person", uid));
        result.put("total", total);
        result.put("styletotal", styletotal);
        return result;
    }

    /**
     * 返回盘点单总金额
     * @param stockCheckDetailsQuery
     * @return
     */
    @Override
    public Map<String, Object> selectTotal(StockCheckDetailsQuery stockCheckDetailsQuery) {
        Map<String, Object> result=new HashMap<>();
       Double total= baseMapper.selectTotal(stockCheckDetailsQuery);
        result.put("total",null==total?0:total);
        return result;
    }
}


